package com.itheima.health.security;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.health.pojo.Permission;
import com.itheima.health.pojo.Role;
import com.itheima.health.pojo.User;
import com.itheima.health.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SecurityUserDetailsService implements UserDetailsService {

	//依赖注入UserService
	@Reference
	private UserService userService;

	//依赖注入BCrypt密码加密对象
	@Autowired
	private BCryptPasswordEncoder passwordEncoder;

	// 模拟数据库的用户记录，如下User类是health_common中的自定义实体类User
	// 修改Role、Permission，为其增加不带参、带参构造方法
	private static Map<String, User> userDb = new HashMap();
	static {
		User user1 = new User();
		user1.setUsername("admin");
		user1.setPassword("123");
		// 用户权限与角色
		Role role1 = new Role("系统管理员","ROLE_ADMIN");
		role1.getPermissions().add(new Permission("添加权限","add"));
		role1.getPermissions().add(new Permission("删除权限","delete"));
		role1.getPermissions().add(new Permission("更新权限","update"));
		role1.getPermissions().add(new Permission("查询权限","find"));
		user1.getRoles().add(role1);
		userDb.put(user1.getUsername(),user1);

		User userZhangSan = new User();
		userZhangSan.setUsername("zhangsan");
		userZhangSan.setPassword("123");
		Role role2 = new Role("数据分析员","ROLE_READER");
		role2.getPermissions().add(new Permission("查询权限","find"));
		userZhangSan.getRoles().add(role2);
		userDb.put(userZhangSan.getUsername(),userZhangSan);

		User userLisi = new User();
		userLisi.setUsername("lisi");
		userLisi.setPassword("123");
		Role role3 = new Role("运营管理员","ROLE_OMS");;
		role3.getPermissions().add(new Permission("添加权限","add"));
		role3.getPermissions().add(new Permission("更新权限","update"));
		userLisi.getRoles().add(role3);
		userDb.put(userLisi.getUsername(),userLisi);
	}

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		//1.根据用户标识（用户名），从数据库读取用户信息
		User currentUser = userService.findByUsername(username);
		if (currentUser == null) {
			return null;
		}

		//2.提取用户信息的角色与权限关键词信息
		//3.把用户角色与权限关键词封装为List<GrantedAuthority>列表
		List<GrantedAuthority> authorityList = new ArrayList<>();
		//通过当前用户, 得到用户关联的每一个角色
		for (Role role : currentUser.getRoles()) {
			//获取当前角色中的角色关键字 存入到 授权集合中
			authorityList.add(new SimpleGrantedAuthority(role.getKeyword()));
			//通过当前角色,得到角色关联的每一个权限
			for (Permission permission : role.getPermissions()) {
				//获取当前权限中的权限关键字 存入到 授权集合中
				authorityList.add(new SimpleGrantedAuthority(permission.getKeyword()));
			}
		}

		//4.构建UserDetails对象（使用Security框架自动的User类封装），封装用户名、密码（必须是加密过的）及权限角色关键词列表
		String passwordByDB = currentUser.getPassword();
		//如果密码未加密, 必须用默认加密规则加密 {noop}
		//如果密码已加密,则不用使用默认规则加密
		//String passwordByAuth = "{noop}"+passwordByDB;
		//String passwordByAuth = passwordEncoder.encode(passwordByDB);

		UserDetails userDetails =
				new org.springframework.security.core.userdetails.User(currentUser.getUsername(), passwordByDB, authorityList);

		System.out.println("userDetails = " + userDetails);
		return userDetails;
	}
}
